{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XVNFRF1WpKfX"
      },
      "source": [
        "\u003ca target=\"_blank\" href=\"https://colab.research.google.com/github/google-research/big_vision/blob/main/big_vision/configs/proj/image_text/SigLIP2_demo.ipynb\"\u003e\n",
        "  \u003cimg src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/\u003e\n",
        "\u003c/a\u003e"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wR53lePHuiP-"
      },
      "source": [
        "# General information\n",
        "\n",
        "Example colab for SigLIP 2 models described in the [SigLIP 2 paper](https://arxiv.org/abs/2502.14786).\n",
        "\n",
        "**These models are not official Google products and were trained and released for research purposes.**\n",
        "\n",
        "If you find these model(s) useful for your research, consider citing\n",
        "\n",
        "```\n",
        "@article{tschannen2025siglip,\n",
        "  title={SigLIP 2: Multilingual Vision-Language Encoders with Improved Semantic Understanding, Localization, and Dense Features},\n",
        "  author={Tschannen, Michael and Gritsenko, Alexey and Wang, Xiao and Naeem, Muhammad Ferjad and Alabdulmohsin, Ibrahim and Parthasarathy, Nikhil and Evans, Talfan and Beyer, Lucas and Xia, Ye and Mustafa, Basil and H\\'enaff, Olivier and Harmsen, Jeremiah and Steiner, Andreas and Zhai, Xiaohua},\n",
        "  year={2025},\n",
        "  journal={arXiv preprint arXiv:2502.14786}\n",
        "}\n",
        "```\n",
        "\n",
        "If you use our released models in your products, we appreciate any direct feedback. Please contact tschannen@google.com to get in touch.\n",
        "\n",
        "This Colab was forked from the previous version\n",
        "[SigLIP_demo.ipynb](https://colab.research.google.com/github/google-research/big_vision/blob/main/big_vision/configs/proj/image_text/SigLIP_demo.ipynb)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "kXSdSXVg2PAI",
        "outputId": "bf11ea75-e6b2-447d-c511-7a5df2c445a8"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Tue Mar  4 18:37:57 2025       \n",
            "+-----------------------------------------------------------------------------------------+\n",
            "| NVIDIA-SMI 550.54.15              Driver Version: 550.54.15      CUDA Version: 12.4     |\n",
            "|-----------------------------------------+------------------------+----------------------+\n",
            "| GPU  Name                 Persistence-M | Bus-Id          Disp.A | Volatile Uncorr. ECC |\n",
            "| Fan  Temp   Perf          Pwr:Usage/Cap |           Memory-Usage | GPU-Util  Compute M. |\n",
            "|                                         |                        |               MIG M. |\n",
            "|=========================================+========================+======================|\n",
            "|   0  Tesla T4                       Off |   00000000:00:04.0 Off |                    0 |\n",
            "| N/A   36C    P8             10W /   70W |       0MiB /  15360MiB |      0%      Default |\n",
            "|                                         |                        |                  N/A |\n",
            "+-----------------------------------------+------------------------+----------------------+\n",
            "                                                                                         \n",
            "+-----------------------------------------------------------------------------------------+\n",
            "| Processes:                                                                              |\n",
            "|  GPU   GI   CI        PID   Type   Process name                              GPU Memory |\n",
            "|        ID   ID                                                               Usage      |\n",
            "|=========================================================================================|\n",
            "|  No running processes found                                                             |\n",
            "+-----------------------------------------------------------------------------------------+\n",
            "  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m319.7/319.7 kB\u001b[0m \u001b[31m6.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m230.2/230.2 MB\u001b[0m \u001b[31m5.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m5.3/5.3 MB\u001b[0m \u001b[31m92.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m367.1/367.1 kB\u001b[0m \u001b[31m25.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m104.3/104.3 MB\u001b[0m \u001b[31m8.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m894.1/894.1 kB\u001b[0m \u001b[31m46.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.5/76.5 kB\u001b[0m \u001b[31m6.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Building wheel for clu (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Building wheel for flaxformer (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Building wheel for panopticapi (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m89.7/89.7 kB\u001b[0m \u001b[31m4.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "  Building wheel for crcmod (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
            "Collecting flax==0.8.5\n",
            "  Downloading flax-0.8.5-py3-none-any.whl.metadata (10 kB)\n",
            "Requirement already satisfied: numpy\u003e=1.22 in /usr/local/lib/python3.11/dist-packages (from flax==0.8.5) (1.26.4)\n",
            "Requirement already satisfied: jax\u003e=0.4.27 in /usr/local/lib/python3.11/dist-packages (from flax==0.8.5) (0.4.33)\n",
            "Requirement already satisfied: msgpack in /usr/local/lib/python3.11/dist-packages (from flax==0.8.5) (1.1.0)\n",
            "Requirement already satisfied: optax in /usr/local/lib/python3.11/dist-packages (from flax==0.8.5) (0.2.4)\n",
            "Requirement already satisfied: orbax-checkpoint in /usr/local/lib/python3.11/dist-packages (from flax==0.8.5) (0.6.4)\n",
            "Requirement already satisfied: tensorstore in /usr/local/lib/python3.11/dist-packages (from flax==0.8.5) (0.1.72)\n",
            "Requirement already satisfied: rich\u003e=11.1 in /usr/local/lib/python3.11/dist-packages (from flax==0.8.5) (13.9.4)\n",
            "Requirement already satisfied: typing-extensions\u003e=4.2 in /usr/local/lib/python3.11/dist-packages (from flax==0.8.5) (4.12.2)\n",
            "Requirement already satisfied: PyYAML\u003e=5.4.1 in /usr/local/lib/python3.11/dist-packages (from flax==0.8.5) (6.0.2)\n",
            "Requirement already satisfied: jaxlib\u003c=0.4.33,\u003e=0.4.33 in /usr/local/lib/python3.11/dist-packages (from jax\u003e=0.4.27-\u003eflax==0.8.5) (0.4.33)\n",
            "Requirement already satisfied: ml-dtypes\u003e=0.2.0 in /usr/local/lib/python3.11/dist-packages (from jax\u003e=0.4.27-\u003eflax==0.8.5) (0.4.1)\n",
            "Requirement already satisfied: opt-einsum in /usr/local/lib/python3.11/dist-packages (from jax\u003e=0.4.27-\u003eflax==0.8.5) (3.4.0)\n",
            "Requirement already satisfied: scipy\u003e=1.10 in /usr/local/lib/python3.11/dist-packages (from jax\u003e=0.4.27-\u003eflax==0.8.5) (1.13.1)\n",
            "Requirement already satisfied: markdown-it-py\u003e=2.2.0 in /usr/local/lib/python3.11/dist-packages (from rich\u003e=11.1-\u003eflax==0.8.5) (3.0.0)\n",
            "Requirement already satisfied: pygments\u003c3.0.0,\u003e=2.13.0 in /usr/local/lib/python3.11/dist-packages (from rich\u003e=11.1-\u003eflax==0.8.5) (2.18.0)\n",
            "Requirement already satisfied: absl-py\u003e=0.7.1 in /usr/local/lib/python3.11/dist-packages (from optax-\u003eflax==0.8.5) (1.4.0)\n",
            "Requirement already satisfied: chex\u003e=0.1.87 in /usr/local/lib/python3.11/dist-packages (from optax-\u003eflax==0.8.5) (0.1.89)\n",
            "Requirement already satisfied: etils[epy] in /usr/local/lib/python3.11/dist-packages (from optax-\u003eflax==0.8.5) (1.12.0)\n",
            "Requirement already satisfied: nest_asyncio in /usr/local/lib/python3.11/dist-packages (from orbax-checkpoint-\u003eflax==0.8.5) (1.6.0)\n",
            "Requirement already satisfied: protobuf in /usr/local/lib/python3.11/dist-packages (from orbax-checkpoint-\u003eflax==0.8.5) (4.25.6)\n",
            "Requirement already satisfied: humanize in /usr/local/lib/python3.11/dist-packages (from orbax-checkpoint-\u003eflax==0.8.5) (4.11.0)\n",
            "Requirement already satisfied: toolz\u003e=0.9.0 in /usr/local/lib/python3.11/dist-packages (from chex\u003e=0.1.87-\u003eoptax-\u003eflax==0.8.5) (0.12.1)\n",
            "Requirement already satisfied: mdurl~=0.1 in /usr/local/lib/python3.11/dist-packages (from markdown-it-py\u003e=2.2.0-\u003erich\u003e=11.1-\u003eflax==0.8.5) (0.1.2)\n",
            "Requirement already satisfied: fsspec in /usr/local/lib/python3.11/dist-packages (from etils[epath,epy]-\u003eorbax-checkpoint-\u003eflax==0.8.5) (2024.10.0)\n",
            "Requirement already satisfied: importlib_resources in /usr/local/lib/python3.11/dist-packages (from etils[epath,epy]-\u003eorbax-checkpoint-\u003eflax==0.8.5) (6.5.2)\n",
            "Requirement already satisfied: zipp in /usr/local/lib/python3.11/dist-packages (from etils[epath,epy]-\u003eorbax-checkpoint-\u003eflax==0.8.5) (3.21.0)\n",
            "Downloading flax-0.8.5-py3-none-any.whl (731 kB)\n",
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m731.3/731.3 kB\u001b[0m \u001b[31m8.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25hInstalling collected packages: flax\n",
            "  Attempting uninstall: flax\n",
            "    Found existing installation: flax 0.10.4\n",
            "    Uninstalling flax-0.10.4:\n",
            "      Successfully uninstalled flax-0.10.4\n",
            "Successfully installed flax-0.8.5\n",
            "/content/big_vision\n"
          ]
        }
      ],
      "source": [
        "#@markdown # Environment setup\n",
        "#@markdown Tested on GPU, TPU, and CPU with ViT-B/16 @256px.\n",
        "import os\n",
        "if 'NVIDIA_PRODUCT_NAME' in os.environ:\n",
        "  !nvidia-smi\n",
        "import jax\n",
        "jax.devices()\n",
        "\n",
        "\n",
        "# Get latest version of big_vision codebase.\n",
        "!git clone --quiet --branch=main --depth=1 https://github.com/google-research/big_vision\n",
        "!cd big_vision \u0026\u0026 git pull --rebase --quiet\n",
        "!pip -q install -r big_vision/big_vision/requirements.txt\n",
        "# Gives us ~2x faster gsutil cp to get the model checkpoints.\n",
        "!pip3 -q install --no-cache-dir -U crcmod\n",
        "\n",
        "%cd big_vision\n",
        "\n",
        "\n",
        "import numpy as np\n",
        "import matplotlib as mpl\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "%matplotlib inline\n",
        "%config InlineBackend.figure_format = 'retina'\n",
        "\n",
        "import jax\n",
        "import jax.numpy as jnp\n",
        "import ml_collections\n",
        "\n",
        "from google.colab.output import _publish as publish"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "ezmzqkFspGXS"
      },
      "outputs": [],
      "source": [
        "#@markdown Image credit:\n",
        "\n",
        "#@markdown - The apple and apple + iPod images are from OpenAI.\n",
        "#@markdown - Cows on beach were created by Chitwan Saharia using the Imagen model and shared with permission.\n",
        "#@markdown - [Cold drink on hot day](https://unsplash.com/fr/photos/hQHm2D1fH70).\n",
        "#@markdown - [Hot drink on cold day](https://www.rawpixel.com/image/3282934).\n",
        "#@markdown - The remaining pictures are personal photos taken by the SigLIP1 authors.\n",
        "\n",
        "!wget -q https://cdn.openai.com/multimodal-neurons/assets/apple/apple-ipod.jpg\n",
        "!wget -q https://cdn.openai.com/multimodal-neurons/assets/apple/apple-blank.jpg\n",
        "!wget -q 'https://images.unsplash.com/photo-1566467021888-b03548769dd1?ixlib=rb-4.0.3\u0026q=85\u0026fm=jpg\u0026crop=entropy\u0026cs=srgb\u0026dl=svetlana-gumerova-hQHm2D1fH70-unsplash.jpg\u0026w=640' -O cold_drink.jpg\n",
        "!wget -q 'https://images.rawpixel.com/image_1300/czNmcy1wcml2YXRlL3Jhd3BpeGVsX2ltYWdlcy93ZWJzaXRlX2NvbnRlbnQvbHIvdXB3azU4ODU5NzY1LXdpa2ltZWRpYS1pbWFnZS1rb3diMmhkeC5qcGc.jpg' -O hot_drink.jpg\n",
        "!wget -q https://storage.googleapis.com/big_vision/siglip/authors.jpg\n",
        "!wget -q https://storage.googleapis.com/big_vision/siglip/siglip.jpg\n",
        "!wget -q https://storage.googleapis.com/big_vision/siglip/caffeine.jpg\n",
        "!wget -q https://storage.googleapis.com/big_vision/siglip/robosign.jpg\n",
        "!wget -q https://storage.googleapis.com/big_vision/siglip/fried_fish.jpeg\n",
        "!wget -q 'https://pbs.twimg.com/media/FTyEyxyXsAAyKPc?format=jpg\u0026name=small' -O cow_beach.jpg\n",
        "!wget -q 'https://storage.googleapis.com/big_vision/siglip/cow_beach2.jpg' -O cow_beach2.jpg\n",
        "!wget -q 'https://pbs.twimg.com/media/Frb6NIEXwAA8-fI?format=jpg\u0026name=medium' -O mountain_view.jpg\n",
        "!wget -q https://storage.googleapis.com/big_vision/siglip2/siglip2_screenshot.jpg\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "byHpmgAO6inM"
      },
      "source": [
        "# Choose and load model, perform inference"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "0DsOabGD7MRG",
        "outputId": "a0d54aa3-6543-48e8-ccb6-4c2048a0b7c7"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Copying gs://big_vision/siglip2/siglip2_so400m16_256.npz...\n",
            "\\ [1 files][  4.2 GiB/  4.2 GiB]   86.7 MiB/s                                   \n",
            "Operation completed over 1 objects/4.2 GiB.                                      \n"
          ]
        }
      ],
      "source": [
        "# Pick your hero: (WHEN CHANGING THIS, RERUN IMAGE/TEXT EMBEDDING CELLS)\n",
        "# Give this cell 1-3mins.\n",
        "\n",
        "# VARIANT, RES = 'B/32', 256\n",
        "# VARIANT, RES = 'B/16', 224\n",
        "# VARIANT, RES = 'B/16', 256\n",
        "# VARIANT, RES = 'B/16', 384\n",
        "# VARIANT, RES = 'B/16', 512\n",
        "# VARIANT, RES, N_PATCHES = 'B/16', 'naflex', 256\n",
        "# VARIANT, RES = 'L/16', 256\n",
        "# VARIANT, RES = 'L/16', 384\n",
        "# VARIANT, RES = 'L/16', 512\n",
        "VARIANT, RES = 'So400m/16', 256\n",
        "# VARIANT, RES = 'So400m/16', 384\n",
        "# VARIANT, RES = 'So400m/16', 512\n",
        "# VARIANT, RES, N_PATCHES = 'So400m/16', 'naflex', 256\n",
        "# VARIANT, RES = 'So400m/14', 224\n",
        "# VARIANT, RES = 'So400m/14', 384\n",
        "# VARIANT, RES = 'g-opt/16', 256\n",
        "# VARIANT, RES = 'g-opt/16', 384\n",
        "\n",
        "CKPT = f'siglip2_{VARIANT.lower().replace(\"/\", \"\")}_{RES}.npz'\n",
        "TXTVARIANT, PATCH_SIZE = VARIANT.split('/')\n",
        "EMBDIM = {'B': 768, 'L': 1024, 'So400m': 1152, 'g-opt': 1536}[TXTVARIANT]\n",
        "# Note: The g-opt vision encoder is paired with a So400m text encoder\n",
        "TXTVARIANT = 'So400m' if TXTVARIANT == 'g-opt' else TXTVARIANT\n",
        "PATCH_SIZE = int(PATCH_SIZE)\n",
        "VOCAB = 256_000\n",
        "SEQLEN = 64\n",
        "\n",
        "# It is significantly faster to first copy the checkpoint (30s vs 8m30 for B and 1m vs ??? for L)\n",
        "!test -f /tmp/{CKPT} || gsutil cp gs://big_vision/siglip2/{CKPT} /tmp/\n",
        "\n",
        "import big_vision.models.proj.image_text.two_towers as model_mod\n",
        "\n",
        "model_cfg = ml_collections.ConfigDict(dict(\n",
        "    image_model='vit',\n",
        "    image=dict(\n",
        "        pool_type='map',\n",
        "        scan=True,\n",
        "        variant=VARIANT,\n",
        "    ),\n",
        "    text_model='proj.image_text.text_transformer',\n",
        "    text=dict(\n",
        "        scan=True,\n",
        "        variant=TXTVARIANT,\n",
        "        vocab_size=256_000,\n",
        "    ),\n",
        "    out_dim=[None, EMBDIM],\n",
        "    bias_init=-10,  # without this arg, no \"b\" param is added\n",
        "))\n",
        "if RES == 'naflex':\n",
        "  model_cfg.image_model = 'proj.image_text.naflex_vit'\n",
        "  model_cfg.image = dict(\n",
        "      pool_type='map',\n",
        "      nposemb=16,\n",
        "      posemb='learn_2d',\n",
        "      variant='B'\n",
        "  )\n",
        "\n",
        "model = model_mod.Model(**model_cfg)\n",
        "\n",
        "# Using `init_params` is slower but will lead to `load` below performing sanity-checks.\n",
        "# init_params = jax.jit(model.init, backend=\"cpu\")(jax.random.PRNGKey(42), jnp.zeros([1, RES, RES, 3], jnp.float32), jnp.zeros([1, SEQLEN], jnp.int32))['params']\n",
        "init_params = None  # Faster but bypasses loading sanity-checks.\n",
        "\n",
        "params = model_mod.load(init_params, f'/tmp/{CKPT}', model_cfg)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "FOsMPR6Gg3Sn"
      },
      "outputs": [],
      "source": [
        "# # inspect params:\n",
        "# from clu import parameter_overview\n",
        "# print(parameter_overview.get_parameter_overview(params))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "xmuXfCfBjgeF",
        "outputId": "f8c2323f-25fe-4fe9-9d4b-bfedc62b60f3"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "imgs (11, 256, 256, 3)\n",
            "zimg (11, 1152)\n"
          ]
        }
      ],
      "source": [
        "#@title Load and embed images\n",
        "\n",
        "import big_vision.pp.builder as pp_builder\n",
        "import big_vision.pp.ops_general\n",
        "import big_vision.pp.ops_image\n",
        "import big_vision.pp.ops_text\n",
        "import big_vision.pp.proj.image_text.ops_naflex\n",
        "import big_vision.pp.proj.paligemma.ops\n",
        "import PIL\n",
        "\n",
        "images = [PIL.Image.open(fname) for fname in [\n",
        "    'apple-ipod.jpg',\n",
        "    'apple-blank.jpg',\n",
        "    'cold_drink.jpg',\n",
        "    'hot_drink.jpg',\n",
        "    'caffeine.jpg',\n",
        "    'siglip.jpg',\n",
        "    'authors.jpg',\n",
        "    'robosign.jpg',\n",
        "    'cow_beach.jpg',\n",
        "    'cow_beach2.jpg',\n",
        "    'mountain_view.jpg',\n",
        "]]\n",
        "\n",
        "get_pp_naflex = lambda n_patches, patch_size: pp_builder.get_preprocess_fn('|'.join((\n",
        "    'value_range(-1, 1)',\n",
        "    f'resize_to_sequence({patch_size}, {n_patches}, outkey=\"image\")',\n",
        "    f'patchify({patch_size}, key=\"image\")',\n",
        "    'flatten([\"image\"])',\n",
        "    f'pad_to_shape(key=\"image/patches\", shape=({n_patches}, None))',\n",
        "    f'pad_to_shape(key=\"image/type\", shape=({n_patches},))',\n",
        "    f'pad_to_shape(key=\"image/yidx\", shape=({n_patches},))',\n",
        "    f'pad_to_shape(key=\"image/xidx\", shape=({n_patches},))',\n",
        "    'tuplify([\"image/patches\", \"image/type\", \"image/yidx\", \"image/xidx\"], \"image\")',\n",
        ")))\n",
        "\n",
        "if RES == 'naflex':\n",
        "  # See section \"NaFlex\" below for a comparison of this preprocessing with\n",
        "  # resize to square.\n",
        "  pp_img = get_pp_naflex(N_PATCHES, PATCH_SIZE)\n",
        "  imgs = [pp_img(dict(image=np.array(image)))['image'] for image in images]\n",
        "  imgs = tuple(np.stack(_) for _ in zip(*imgs))\n",
        "  print('imgs', tuple(x.shape for x in imgs))\n",
        "else:\n",
        "  pp_img = pp_builder.get_preprocess_fn(f'resize({RES})|value_range(-1, 1)')\n",
        "  imgs = np.array([pp_img({'image': np.array(image)})['image'] for image in images])\n",
        "  print('imgs', imgs.shape)\n",
        "\n",
        "zimg, _, out = model.apply({'params': params}, imgs, None)\n",
        "\n",
        "print('zimg', zimg.shape)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "KGrpkRTtjU-L",
        "outputId": "f36af86f-d844-4faf-ad9b-fd2dae91c0a1"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "(18, 64) (18, 1152)\n"
          ]
        }
      ],
      "source": [
        "#@title Tokenize and embed texts\n",
        "\n",
        "# texts with translations into random languages\n",
        "texts_dict = {\n",
        "    'an apple': 'tufaha',  # Swahili\n",
        "    'a picture of an apple': 'ένα μήλο',  # Greek (Modern)\n",
        "    'an ipod': 'айпод',  # Russian\n",
        "    'an apple with a note saying \"ipod\"': 'apple na nóta ag rá \"ipod\"',  # Irish\n",
        "    'a cold drink on a hot day': 'en kold drink på en varm dag', # Danish\n",
        "    'a hot drink on a cold day': 'een hete drank op een koude dag', # Dutch\n",
        "    'a photo of a cold drink on a hot day': '炎热天气里一杯冷饮的照片', # Chinese\n",
        "    'a photo of a hot drink on a cold day': 'foto cangkir panas dina dinten tiis',  # Sundanese\n",
        "    #\n",
        "    'a photo of two guys in need of caffeine': 'एक तस्वीर जिसमें दो लोगों को कैफीन की ज़रूरत है',  # Hindi\n",
        "    'a photo of two guys in need of water': 'o imagine a doi tipi care au nevoie de apă',  # Romanian\n",
        "    'a photo of the SigLIP authors': 'foto para penulis SigLIP',  # Indonesian\n",
        "    'a photo of a rock band': 'ロックバンドの写真', # Japanese\n",
        "    'a photo of researchers at Google Brain': 'foto av forskare på Google Brain', # Swedish\n",
        "    'a photo of researchers at OpenAI': 'OpenAI:n tutkijoiden kuva',  # Finnish\n",
        "    #\n",
        "    'cow': 'sapi',  # Indonesian\n",
        "    'a cow in a tuxedo': 'une vache en smoking',  # French\n",
        "    'a cow on the beach': 'פרה על החוף', # Hebrew\n",
        "    #\n",
        "    # Croatian:\n",
        "    'a picture of a laptop with the lockscreen on, a cup of cappucino, salt and pepper grinders. The view through the window reveals lake Zürich and the Alps in the background of the city.': \"slika prijenosnog računala sa zaključanim zaslonom, šalica cappuccina, mlinci za sol i papar. Pogled kroz prozor otkriva jezero Zürich i Alpe u pozadini grada.\",\n",
        "}\n",
        "\n",
        "# ‼️ NOTE: SigLIP 2 models work best with lowercase texts\n",
        "pp_txt = pp_builder.get_preprocess_fn(f'lower(key=\"text\")|tok(length={SEQLEN}, model=\"gemma\", bos=\"no\", eos=\"sticky\", key=\"text\")')\n",
        "\n",
        "\n",
        "def embed_texts(texts):\n",
        "  txts = np.array([pp_txt({'text': text})['text'] for text in texts])\n",
        "  _, ztxt, out = model.apply({'params': params}, None, txts)\n",
        "  return txts, ztxt, dict(t=out['t'], b=out['b'])\n",
        "\n",
        "\n",
        "txts, ztxt, out = embed_texts(texts_dict)\n",
        "print(txts.shape, ztxt.shape)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "TIdAVw9VGEAw",
        "outputId": "15496356-b38e-4646-88d2-b4e62edcf782"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Learned temperature 109.9, learned bias: -15.9\n",
            "21.8% that image 0 is 'an apple'\n",
            "33.6% that image 0 is 'a picture of an apple'\n"
          ]
        }
      ],
      "source": [
        "# This is how to get all probabilities:\n",
        "print(f\"Learned temperature {out['t'].item():.1f}, learned bias: {out['b'].item():.1f}\")\n",
        "probs = jax.nn.sigmoid(zimg @ ztxt.T * out['t'] + out['b'])\n",
        "print(f\"{probs[0][0]:.1%} that image 0 is '{list(texts_dict)[0]}'\")\n",
        "print(f\"{probs[0][1]:.1%} that image 0 is '{list(texts_dict)[1]}'\")"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "f_kXZhQ2ovIi"
      },
      "outputs": [],
      "source": [
        "# @title Pretty demo (code)\n",
        "from IPython.display import Javascript, HTML\n",
        "\n",
        "DEMO_IMG_SIZE = 96\n",
        "\n",
        "import base64\n",
        "import io\n",
        "\n",
        "def bv2rgb(bv_img):\n",
        "  return (bv_img * 127.5 + 127.5).astype(np.uint8)\n",
        "\n",
        "def img2html(img):\n",
        "  with io.BytesIO() as buf:\n",
        "    img.save(buf, format=\"JPEG\")\n",
        "    enc_img = buf.getvalue()\n",
        "  img_data = base64.b64encode(np.ascontiguousarray(enc_img)).decode('ascii')\n",
        "  return f'\u003cimg src=\"data:image/jpeg;base64,{img_data}\"/\u003e'\n",
        "\n",
        "\n",
        "def make_table(zimg, ztxt, images, texts, out):\n",
        "  # The default learnable bias is a little conservative. Play around with it!\n",
        "  t, b = out['t'].item(), out['b'].item()\n",
        "  tempered_logits = zimg @ ztxt.T * t\n",
        "  probs = 1 / (1 + np.exp(-tempered_logits - b))\n",
        "  publish.javascript(f\"var logits = {tempered_logits.tolist()};\")\n",
        "\n",
        "  def color(p):\n",
        "    return mpl.colors.rgb2hex(mpl.cm.Greens(p / 2)) if p \u003e= 0.01 else \"transparent\"\n",
        "\n",
        "  publish.javascript(f\"var cmap = {[color(x) for x in np.linspace(0, 1, 50)]};\")\n",
        "  def cell(x, iimg, itxt):\n",
        "    return f\"\u003ctd id=td_{iimg}_{itxt} style=background-color:{color(x)} class=pct\u003e\u003cpre id=p_{iimg}_{itxt}\u003e{x * 100:\u003e4.0f}%\u003c/pre\u003e\"\n",
        "\n",
        "  html = f'''\n",
        "  \u003cp\u003e\n",
        "  \u003clabel for=b\u003eBias value:\u003c/label\u003e\n",
        "  \u003cinput id=b type=range min=-20 max=0 step=0.1 name=b value={b} style=vertical-align:middle\u003e\n",
        "  \u003coutput id=value\u003e\u003c/output\u003e\n",
        "  \u003c/p\u003e\n",
        "  '''\n",
        "\n",
        "  html += \"\u003ctable\u003e\\n\"\n",
        "  html += \"\u003ctr\u003e\"\n",
        "  html += \"\".join([f\"\u003ctd style='width:{DEMO_IMG_SIZE}px;line-height:0'\u003e\" + img2html(img.resize([DEMO_IMG_SIZE, DEMO_IMG_SIZE])) for img in images])\n",
        "  html += \"\u003ctd\u003e\"\n",
        "  for itxt, txt in enumerate(texts):\n",
        "    html += f\"\u003ctr\u003e\" + \"\".join([cell(probs[iimg, itxt], iimg, itxt) for iimg in range(len(images))]) + f\"\u003ctd class=txt\u003e{txt}\"\n",
        "\n",
        "  publish.css(r\"\"\"\n",
        "  table {\n",
        "    border-collapse: collapse;\n",
        "  }\n",
        "\n",
        "  tr {\n",
        "    border: 1px transparent;\n",
        "  }\n",
        "\n",
        "  tr:nth-child(odd) {\n",
        "    background-color: #F5F5F5;\n",
        "  }\n",
        "\n",
        "  tr:hover {\n",
        "    background-color: lightyellow;\n",
        "    border: 1px solid black;\n",
        "  }\n",
        "\n",
        "  td.pct {\n",
        "    text-align: center;\n",
        "  }\n",
        "  \"\"\")\n",
        "  publish.html(html)\n",
        "\n",
        "  # JS code to compute and write all probs from the logits.\n",
        "  display(Javascript('''\n",
        "  function update(b) {\n",
        "    for(var iimg = 0; iimg \u003c logits.length; iimg++) {\n",
        "      for(var itxt = 0; itxt \u003c logits[iimg].length; itxt++) {\n",
        "        const el = document.getElementById(`p_${iimg}_${itxt}`);\n",
        "        const p = Math.round(100 / (1 + Math.exp(-logits[iimg][itxt] - b)));\n",
        "        const pad = p \u003c 10.0 ? '  ' : p \u003c 100.0 ? ' ' : ''\n",
        "        el.innerHTML = pad + (p).toFixed(0) + '%';\n",
        "\n",
        "        const td = document.getElementById(`td_${iimg}_${itxt}`);\n",
        "        const c = cmap[Math.round(p / 100 * (cmap.length - 1))];\n",
        "        td.style.backgroundColor = c;\n",
        "      }\n",
        "    }\n",
        "  }\n",
        "  '''))\n",
        "\n",
        "  # JS code to connect the bias value slider\n",
        "  display(Javascript('''\n",
        "  const value = document.querySelector(\"#value\");\n",
        "  const input = document.querySelector(\"#b\");\n",
        "  value.textContent = input.value;\n",
        "  input.addEventListener(\"input\", (event) =\u003e {\n",
        "    value.textContent = event.target.value;\n",
        "    update(event.target.value);\n",
        "  });\n",
        "  '''))\n",
        "\n",
        "  # Make the cell output as large as the table to avoid annoying scrollbars.\n",
        "  display(Javascript(f'update({b})'))\n",
        "  display(Javascript('google.colab.output.resizeIframeToContent()'))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 515
        },
        "id": "mt5BIywzzA6c",
        "outputId": "7e92d9f8-eaf8-44cb-9092-7e06f4fac390"
      },
      "outputs": [
        {
          "data": {
            "application/javascript": [
              "var logits = [[14.656767845153809, 15.250247955322266, 15.409202575683594, 19.771230697631836, 2.2841110229492188, 3.2212440967559814, 2.7505900859832764, 2.945586681365967, 1.249023675918579, -0.022008903324604034, 4.742644786834717, 0.2296551764011383, -1.9878309965133667, -1.3340283632278442, 0.16120955348014832, -7.615262031555176, -5.1106181144714355, -8.441411972045898], [16.266162872314453, 17.33416748046875, 4.963876247406006, 9.065200805664062, 4.221234321594238, 3.199340343475342, 3.3866782188415527, 1.9877198934555054, -1.8332914113998413, -0.5539354085922241, 2.5022826194763184, -3.1470394134521484, -2.840461492538452, -4.132590293884277, 2.5552444458007812, -6.645838260650635, -3.538269281387329, -8.712821006774902], [1.8294894695281982, 2.154853343963623, -0.7122278213500977, -3.929692506790161, 15.371567726135254, 5.8843841552734375, 15.19970417022705, 5.412536144256592, 2.618687868118286, 2.752964973449707, 4.505246639251709, -1.6640056371688843, -5.128721237182617, -4.339777946472168, -1.4124987125396729, -9.368490219116211, -3.787917375564575, -7.841649055480957], [2.9122354984283447, 2.4692718982696533, 2.459583282470703, -4.101287364959717, 4.548985958099365, 15.888904571533203, 5.545042514801025, 18.007904052734375, 2.996645450592041, -3.7164523601531982, -0.09089484810829163, -3.3227603435516357, -5.767429351806641, -6.667675495147705, 0.5110976696014404, -7.719865798950195, -4.184369087219238, -5.109359264373779], [-1.0981005430221558, -0.11852116882801056, -1.1732755899429321, -7.526024341583252, 4.226718425750732, 3.3711671829223633, 4.0914788246154785, 2.414170026779175, 20.417871475219727, 10.825191497802734, 11.764508247375488, 1.3084189891815186, 8.395318984985352, 9.139975547790527, -0.11757967621088028, -11.61832332611084, -5.792989253997803, 2.866032361984253], [0.23675498366355896, 1.2888647317886353, 0.12354141473770142, 3.171550750732422, -0.03542157635092735, -2.6963112354278564, -0.2601011395454407, -3.704585075378418, 4.161721706390381, 4.016524314880371, 26.05571746826172, 4.814850330352783, 16.42120361328125, 14.271191596984863, -2.4880902767181396, -9.752284049987793, -9.190740585327148, -3.5817220211029053], [1.078748106956482, 1.369918704032898, -0.3256940245628357, -2.161975383758545, 1.5595654249191284, -0.008188785053789616, 0.1384943276643753, -1.9556262493133545, 5.385950088500977, 2.41086745262146, 16.263961791992188, 4.138530254364014, 22.473264694213867, 18.332529067993164, -2.502660036087036, -9.021139144897461, -7.785128116607666, -1.456052541732788], [0.830745279788971, 2.6711432933807373, 1.1853156089782715, -0.051070623099803925, -4.069701194763184, 0.5147737860679626, -3.8544862270355225, 1.2381788492202759, -0.8294660449028015, 2.6137824058532715, 4.02204704284668, 0.727441132068634, -2.1278531551361084, -0.1010865867137909, 1.333038330078125, -5.051750183105469, -6.807021141052246, -2.0184223651885986], [-0.8872398138046265, 0.4818684756755829, -1.6223139762878418, -7.974726676940918, 3.2184135913848877, -1.5331275463104248, 1.2972863912582397, -3.3138039112091064, -2.8257241249084473, -0.2787041664123535, -1.9446015357971191, -5.636784553527832, -5.324060440063477, -5.12062406539917, 13.344278335571289, 6.2044501304626465, 21.382110595703125, -6.001667499542236], [1.0758713483810425, 1.9333736896514893, -0.2656210660934448, -6.8738508224487305, 2.1863884925842285, -1.0240341424942017, 0.3531090319156647, -2.908724546432495, -1.3156943321228027, -0.13916334509849548, -0.8485345244407654, -3.262017011642456, -3.924159049987793, -4.24848747253418, 13.137842178344727, 22.693538665771484, 17.857364654541016, -3.6404786109924316], [0.6692630648612976, 2.067216634750366, 1.699018120765686, -1.8247333765029907, 5.062845706939697, 9.979086875915527, 5.2289862632751465, 10.712607383728027, 6.570303440093994, -0.30220529437065125, 6.702491283416748, -3.121782064437866, 0.9961336255073547, 2.7932493686676025, 2.873249053955078, -2.8172128200531006, 1.5813153982162476, 32.34162139892578]];\n",
              "//# sourceURL=js_d53fa15802"
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/javascript": [
              "var cmap = ['transparent', '#f6fcf4', '#f4fbf2', '#f3faf0', '#f1faee', '#f0f9ec', '#eff9eb', '#edf8e9', '#ecf8e8', '#eaf7e6', '#e8f6e4', '#e7f6e3', '#e5f5e1', '#e4f5df', '#e1f3dc', '#def2d9', '#dcf2d7', '#daf0d4', '#d7efd1', '#d5efcf', '#d2edcc', '#d0edca', '#cdecc7', '#cbeac4', '#c9eac2', '#c6e8bf', '#c3e7bc', '#c0e6b9', '#bce4b5', '#bae3b3', '#b6e2af', '#b4e1ad', '#b0dfaa', '#acdea6', '#aadda4', '#a7dba0', '#a3da9d', '#a0d99b', '#9cd797', '#99d595', '#95d391', '#91d28e', '#8ed08b', '#8ace88', '#87cd86', '#83cb82', '#7fc97f', '#7cc87c', '#78c679', '#73c476'];\n",
              "//# sourceURL=js_b212ab59e1"
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "\u003cstyle\u003e\n",
              "  table {\n",
              "    border-collapse: collapse;\n",
              "  }\n",
              "\n",
              "  tr {\n",
              "    border: 1px transparent;\n",
              "  }\n",
              "\n",
              "  tr:nth-child(odd) {\n",
              "    background-color: #F5F5F5;\n",
              "  }\n",
              "\n",
              "  tr:hover {\n",
              "    background-color: lightyellow;\n",
              "    border: 1px solid black;\n",
              "  }\n",
              "\n",
              "  td.pct {\n",
              "    text-align: center;\n",
              "  }\n",
              "  \u003c/style\u003e"
            ],
            "text/plain": [
              "\u003cIPython.core.display.HTML object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "\n",
              "  \u003cp\u003e\n",
              "  \u003clabel for=b\u003eBias value:\u003c/label\u003e\n",
              "  \u003cinput id=b type=range min=-20 max=0 step=0.1 name=b value=-15.932409286499023 style=vertical-align:middle\u003e\n",
              "  \u003coutput id=value\u003e\u003c/output\u003e\n",
              "  \u003c/p\u003e\n",
              "  \u003ctable\u003e\n",
              "\u003ctr\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd\u003e\u003ctr\u003e\u003ctd id=td_0_0 style=background-color:#e8f6e3 class=pct\u003e\u003cpre id=p_0_0\u003e  22%\u003c/pre\u003e\u003ctd id=td_1_0 style=background-color:#bbe4b4 class=pct\u003e\u003cpre id=p_1_0\u003e  58%\u003c/pre\u003e\u003ctd id=td_2_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_0\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ean apple\u003ctr\u003e\u003ctd id=td_0_1 style=background-color:#dbf1d6 class=pct\u003e\u003cpre id=p_0_1\u003e  34%\u003c/pre\u003e\u003ctd id=td_1_1 style=background-color:#98d594 class=pct\u003e\u003cpre id=p_1_1\u003e  80%\u003c/pre\u003e\u003ctd id=td_2_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_1\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea picture of an apple\u003ctr\u003e\u003ctd id=td_0_2 style=background-color:#d7efd1 class=pct\u003e\u003cpre id=p_0_2\u003e  37%\u003c/pre\u003e\u003ctd id=td_1_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_2\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ean ipod\u003ctr\u003e\u003ctd id=td_0_3 style=background-color:#78c679 class=pct\u003e\u003cpre id=p_0_3\u003e  98%\u003c/pre\u003e\u003ctd id=td_1_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_3\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ean apple with a note saying \"ipod\"\u003ctr\u003e\u003ctd id=td_0_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_4 style=background-color:#d8f0d2 class=pct\u003e\u003cpre id=p_2_4\u003e  36%\u003c/pre\u003e\u003ctd id=td_3_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_4\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea cold drink on a hot day\u003ctr\u003e\u003ctd id=td_0_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_5 style=background-color:#c9eac2 class=pct\u003e\u003cpre id=p_3_5\u003e  49%\u003c/pre\u003e\u003ctd id=td_4_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_5\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea hot drink on a cold day\u003ctr\u003e\u003ctd id=td_0_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_6 style=background-color:#dcf2d7 class=pct\u003e\u003cpre id=p_2_6\u003e  32%\u003c/pre\u003e\u003ctd id=td_3_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_6\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea photo of a cold drink on a hot day\u003ctr\u003e\u003ctd id=td_0_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_7 style=background-color:#88ce87 class=pct\u003e\u003cpre id=p_3_7\u003e  89%\u003c/pre\u003e\u003ctd id=td_4_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_7\u003e   1%\u003c/pre\u003e\u003ctd class=txt\u003ea photo of a hot drink on a cold day\u003ctr\u003e\u003ctd id=td_0_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_8 style=background-color:#76c578 class=pct\u003e\u003cpre id=p_4_8\u003e  99%\u003c/pre\u003e\u003ctd id=td_5_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_8\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea photo of two guys in need of caffeine\u003ctr\u003e\u003ctd id=td_0_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_9\u003e   1%\u003c/pre\u003e\u003ctd id=td_5_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_9\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea photo of two guys in need of water\u003ctr\u003e\u003ctd id=td_0_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_10\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_10\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_10\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_10\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_10 style=background-color:#f6fcf4 class=pct\u003e\u003cpre id=p_4_10\u003e   2%\u003c/pre\u003e\u003ctd id=td_5_10 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_5_10\u003e 100%\u003c/pre\u003e\u003ctd id=td_6_10 style=background-color:#bbe4b4 class=pct\u003e\u003cpre id=p_6_10\u003e  58%\u003c/pre\u003e\u003ctd id=td_7_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_10\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_10\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_10\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_10\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea photo of the SigLIP authors\u003ctr\u003e\u003ctd id=td_0_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_11\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea photo of a rock band\u003ctr\u003e\u003ctd id=td_0_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_12 style=background-color:#b5e1ae class=pct\u003e\u003cpre id=p_5_12\u003e  62%\u003c/pre\u003e\u003ctd id=td_6_12 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_6_12\u003e 100%\u003c/pre\u003e\u003ctd id=td_7_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_12\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea photo of researchers at Google Brain\u003ctr\u003e\u003ctd id=td_0_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_13\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_13\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_13\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_13\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_13\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_13 style=background-color:#ecf8e8 class=pct\u003e\u003cpre id=p_5_13\u003e  16%\u003c/pre\u003e\u003ctd id=td_6_13 style=background-color:#83cb82 class=pct\u003e\u003cpre id=p_6_13\u003e  92%\u003c/pre\u003e\u003ctd id=td_7_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_13\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_13\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_13\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_13\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea photo of researchers at OpenAI\u003ctr\u003e\u003ctd id=td_0_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_14 style=background-color:#f2faf0 class=pct\u003e\u003cpre id=p_8_14\u003e   7%\u003c/pre\u003e\u003ctd id=td_9_14 style=background-color:#f3faf0 class=pct\u003e\u003cpre id=p_9_14\u003e   6%\u003c/pre\u003e\u003ctd id=td_10_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_14\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ecow\u003ctr\u003e\u003ctd id=td_0_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_15 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_9_15\u003e 100%\u003c/pre\u003e\u003ctd id=td_10_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_15\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea cow in a tuxedo\u003ctr\u003e\u003ctd id=td_0_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_16 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_8_16\u003e 100%\u003c/pre\u003e\u003ctd id=td_9_16 style=background-color:#8bcf89 class=pct\u003e\u003cpre id=p_9_16\u003e  87%\u003c/pre\u003e\u003ctd id=td_10_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_16\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003ea cow on the beach\u003ctr\u003e\u003ctd id=td_0_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_17 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_10_17\u003e 100%\u003c/pre\u003e\u003ctd class=txt\u003ea picture of a laptop with the lockscreen on, a cup of cappucino, salt and pepper grinders. The view through the window reveals lake Zürich and the Alps in the background of the city."
            ],
            "text/plain": [
              "\u003cIPython.core.display.HTML object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/javascript": [
              "\n",
              "  function update(b) {\n",
              "    for(var iimg = 0; iimg \u003c logits.length; iimg++) {\n",
              "      for(var itxt = 0; itxt \u003c logits[iimg].length; itxt++) {\n",
              "        const el = document.getElementById(`p_${iimg}_${itxt}`);\n",
              "        const p = Math.round(100 / (1 + Math.exp(-logits[iimg][itxt] - b)));\n",
              "        const pad = p \u003c 10.0 ? '  ' : p \u003c 100.0 ? ' ' : ''\n",
              "        el.innerHTML = pad + (p).toFixed(0) + '%';\n",
              "\n",
              "        const td = document.getElementById(`td_${iimg}_${itxt}`);\n",
              "        const c = cmap[Math.round(p / 100 * (cmap.length - 1))];\n",
              "        td.style.backgroundColor = c;\n",
              "      }\n",
              "    }\n",
              "  }\n",
              "  "
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/javascript": [
              "\n",
              "  const value = document.querySelector(\"#value\");\n",
              "  const input = document.querySelector(\"#b\");\n",
              "  value.textContent = input.value;\n",
              "  input.addEventListener(\"input\", (event) =\u003e {\n",
              "    value.textContent = event.target.value;\n",
              "    update(event.target.value);\n",
              "  });\n",
              "  "
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/javascript": [
              "update(-15.932409286499023)"
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/javascript": [
              "google.colab.output.resizeIframeToContent()"
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "make_table(zimg, ztxt, images, texts_dict, out)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 515
        },
        "id": "30FA-NO7KNOP",
        "outputId": "00bf42e2-b5d4-4641-b989-672e61af37d9"
      },
      "outputs": [
        {
          "data": {
            "application/javascript": [
              "var logits = [[4.708954811096191, 10.252580642700195, 11.7265043258667, 11.544998168945312, 0.1305990368127823, 1.5841662883758545, 3.630753755569458, -0.7714423537254333, 0.3038620054721832, 0.9330309629440308, 5.620166301727295, 4.994389057159424, -1.0472909212112427, 4.543239116668701, -2.824063777923584, -5.081585884094238, -6.987623691558838, -2.3818702697753906], [8.171940803527832, 11.17417049407959, 4.432953357696533, 6.457207679748535, 1.3871290683746338, 2.219010353088379, 3.5326123237609863, -0.7986044883728027, -2.825303316116333, 1.1154505014419556, 4.556244373321533, 2.2998785972595215, -2.406578540802002, 4.929878234863281, -1.9565794467926025, -4.75186014175415, -6.194672584533691, -4.585219383239746], [-2.6471810340881348, 3.9581215381622314, -2.9246411323547363, -0.9786444902420044, 14.128297805786133, 4.567025184631348, 11.410842895507812, 1.76983642578125, 4.689402103424072, 1.7969943284988403, 5.961252212524414, 1.7688648700714111, -3.651942491531372, 7.71082878112793, -3.0781638622283936, -2.641646385192871, -2.5421512126922607, 1.7708303928375244], [0.2949942648410797, 1.932803988456726, 3.306114435195923, 2.584017276763916, 2.1844401359558105, 12.037250518798828, 7.571876049041748, 12.411622047424316, 7.1210479736328125, 1.8668016195297241, 5.749546051025391, 3.610408067703247, -3.6449713706970215, 7.799605846405029, -0.9833672642707825, -4.073538780212402, -6.789474010467529, 6.41080379486084], [-2.0145375728607178, -1.0846933126449585, -2.940375804901123, 2.6589603424072266, 5.769614219665527, 4.240757942199707, 7.1254754066467285, 4.012314319610596, 15.3019380569458, 3.6545205116271973, 5.716222763061523, 2.5195000171661377, 9.611126899719238, 9.60205078125, -1.9188376665115356, -5.494052886962891, -5.42561674118042, 8.74514102935791], [-2.7537841796875, -3.5822393894195557, 0.32357507944107056, 7.592442989349365, 0.9119635224342346, -3.0199146270751953, 3.205625057220459, -0.31654486060142517, 4.254082679748535, 0.168704554438591, 13.821099281311035, 2.7867889404296875, 13.22304630279541, 11.5840482711792, -0.5913334488868713, -6.033755302429199, -9.892203330993652, 5.269253730773926], [-3.990476131439209, -1.9461418390274048, -2.113290309906006, 4.550549030303955, 1.036789059638977, -1.5451210737228394, 4.352191925048828, 0.6461118459701538, 5.015008926391602, -1.0808383226394653, 7.48602294921875, 2.4091312885284424, 18.148042678833008, 10.651418685913086, -2.0211689472198486, -6.457880020141602, -9.205273628234863, 3.46785306930542], [-3.516423225402832, -2.8655121326446533, -0.6669525504112244, 1.7112245559692383, -4.795217990875244, -1.1479816436767578, 0.5346255898475647, -2.38808274269104, 1.3803900480270386, 0.5720602869987488, 5.026162624359131, 2.283620595932007, -2.3419137001037598, 9.335556030273438, -1.9925683736801147, -0.6448726654052734, -8.274177551269531, 1.9019465446472168], [-1.2616840600967407, -0.16455139219760895, -1.1095176935195923, 2.245575428009033, 0.3639048933982849, -1.5086716413497925, 5.667880058288574, -0.43802565336227417, -1.7136955261230469, 4.012487411499023, 6.23145866394043, 1.973950982093811, -3.3627028465270996, 7.671400547027588, 11.997048377990723, 8.537683486938477, 18.037771224975586, 1.0273253917694092], [-3.207190990447998, -1.040488362312317, 0.22546111047267914, 3.421861410140991, -0.2788379490375519, -2.991720199584961, 3.0546505451202393, -0.015481832437217236, -0.0560772567987442, 0.8988143801689148, 4.313138484954834, 1.859076976776123, -0.37786176800727844, 8.216859817504883, 11.015033721923828, 19.41145133972168, 15.026349067687988, 1.2226654291152954], [-0.6364625692367554, -3.1751327514648438, -0.228841632604599, 4.9642558097839355, 4.6297149658203125, 7.745206356048584, 6.453392028808594, 4.766838073730469, 8.835647583007812, 3.2101669311523438, 6.487405300140381, 1.499509334564209, 4.8225250244140625, 10.128129005432129, 0.3955494165420532, -0.6124244332313538, -0.9442399144172668, 19.979965209960938]];\n",
              "//# sourceURL=js_8a6424db91"
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/javascript": [
              "var cmap = ['transparent', '#f6fcf4', '#f4fbf2', '#f3faf0', '#f1faee', '#f0f9ec', '#eff9eb', '#edf8e9', '#ecf8e8', '#eaf7e6', '#e8f6e4', '#e7f6e3', '#e5f5e1', '#e4f5df', '#e1f3dc', '#def2d9', '#dcf2d7', '#daf0d4', '#d7efd1', '#d5efcf', '#d2edcc', '#d0edca', '#cdecc7', '#cbeac4', '#c9eac2', '#c6e8bf', '#c3e7bc', '#c0e6b9', '#bce4b5', '#bae3b3', '#b6e2af', '#b4e1ad', '#b0dfaa', '#acdea6', '#aadda4', '#a7dba0', '#a3da9d', '#a0d99b', '#9cd797', '#99d595', '#95d391', '#91d28e', '#8ed08b', '#8ace88', '#87cd86', '#83cb82', '#7fc97f', '#7cc87c', '#78c679', '#73c476'];\n",
              "//# sourceURL=js_b212ab59e1"
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "\u003cstyle\u003e\n",
              "  table {\n",
              "    border-collapse: collapse;\n",
              "  }\n",
              "\n",
              "  tr {\n",
              "    border: 1px transparent;\n",
              "  }\n",
              "\n",
              "  tr:nth-child(odd) {\n",
              "    background-color: #F5F5F5;\n",
              "  }\n",
              "\n",
              "  tr:hover {\n",
              "    background-color: lightyellow;\n",
              "    border: 1px solid black;\n",
              "  }\n",
              "\n",
              "  td.pct {\n",
              "    text-align: center;\n",
              "  }\n",
              "  \u003c/style\u003e"
            ],
            "text/plain": [
              "\u003cIPython.core.display.HTML object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "\n",
              "  \u003cp\u003e\n",
              "  \u003clabel for=b\u003eBias value:\u003c/label\u003e\n",
              "  \u003cinput id=b type=range min=-20 max=0 step=0.1 name=b value=-10.0 style=vertical-align:middle\u003e\n",
              "  \u003coutput id=value\u003e\u003c/output\u003e\n",
              "  \u003c/p\u003e\n",
              "  \u003ctable\u003e\n",
              "\u003ctr\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd style='width:96px;line-height:0'\u003e\u003cimg src=\"\"/\u003e\u003ctd\u003e\u003ctr\u003e\u003ctd id=td_0_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_0\u003e   1%\u003c/pre\u003e\u003ctd id=td_1_0 style=background-color:#edf8ea class=pct\u003e\u003cpre id=p_1_0\u003e  14%\u003c/pre\u003e\u003ctd id=td_2_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_0\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_0 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_0\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003etufaha\u003ctr\u003e\u003ctd id=td_0_1 style=background-color:#bde5b6 class=pct\u003e\u003cpre id=p_0_1\u003e  56%\u003c/pre\u003e\u003ctd id=td_1_1 style=background-color:#9fd899 class=pct\u003e\u003cpre id=p_1_1\u003e  76%\u003c/pre\u003e\u003ctd id=td_2_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_1\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_1 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_1\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003eένα μήλο\u003ctr\u003e\u003ctd id=td_0_2 style=background-color:#90d18d class=pct\u003e\u003cpre id=p_0_2\u003e  85%\u003c/pre\u003e\u003ctd id=td_1_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_2\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_2 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_2\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003eайпод\u003ctr\u003e\u003ctd id=td_0_3 style=background-color:#94d390 class=pct\u003e\u003cpre id=p_0_3\u003e  82%\u003c/pre\u003e\u003ctd id=td_1_3 style=background-color:#f5fbf3 class=pct\u003e\u003cpre id=p_1_3\u003e   3%\u003c/pre\u003e\u003ctd id=td_2_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_3 style=background-color:#f1faee class=pct\u003e\u003cpre id=p_5_3\u003e   8%\u003c/pre\u003e\u003ctd id=td_6_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_3\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_3 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_3\u003e   1%\u003c/pre\u003e\u003ctd class=txt\u003eapple na nóta ag rá \"ipod\"\u003ctr\u003e\u003ctd id=td_0_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_4 style=background-color:#78c679 class=pct\u003e\u003cpre id=p_2_4\u003e  98%\u003c/pre\u003e\u003ctd id=td_3_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_4 style=background-color:#f6fcf4 class=pct\u003e\u003cpre id=p_4_4\u003e   1%\u003c/pre\u003e\u003ctd id=td_5_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_4\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_4 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_4\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003een kold drink på en varm dag\u003ctr\u003e\u003ctd id=td_0_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_5 style=background-color:#88ce87 class=pct\u003e\u003cpre id=p_3_5\u003e  88%\u003c/pre\u003e\u003ctd id=td_4_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_5 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_5\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_5 style=background-color:#f0f9ed class=pct\u003e\u003cpre id=p_10_5\u003e   9%\u003c/pre\u003e\u003ctd class=txt\u003eeen hete drank op een koude dag\u003ctr\u003e\u003ctd id=td_0_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_6 style=background-color:#98d594 class=pct\u003e\u003cpre id=p_2_6\u003e  80%\u003c/pre\u003e\u003ctd id=td_3_6 style=background-color:#f1faee class=pct\u003e\u003cpre id=p_3_6\u003e   8%\u003c/pre\u003e\u003ctd id=td_4_6 style=background-color:#f4fbf1 class=pct\u003e\u003cpre id=p_4_6\u003e   5%\u003c/pre\u003e\u003ctd id=td_5_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_6 style=background-color:#f6fcf4 class=pct\u003e\u003cpre id=p_8_6\u003e   1%\u003c/pre\u003e\u003ctd id=td_9_6 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_6\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_6 style=background-color:#f5fbf3 class=pct\u003e\u003cpre id=p_10_6\u003e   3%\u003c/pre\u003e\u003ctd class=txt\u003e炎热天气里一杯冷饮的照片\u003ctr\u003e\u003ctd id=td_0_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_7 style=background-color:#83cb82 class=pct\u003e\u003cpre id=p_3_7\u003e  92%\u003c/pre\u003e\u003ctd id=td_4_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_7\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_7 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_7\u003e   1%\u003c/pre\u003e\u003ctd class=txt\u003efoto cangkir panas dina dinten tiis\u003ctr\u003e\u003ctd id=td_0_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_8 style=background-color:#f4fbf1 class=pct\u003e\u003cpre id=p_3_8\u003e   5%\u003c/pre\u003e\u003ctd id=td_4_8 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_4_8\u003e 100%\u003c/pre\u003e\u003ctd id=td_5_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_8\u003e   1%\u003c/pre\u003e\u003ctd id=td_7_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_8 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_8\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_8 style=background-color:#e6f5e1 class=pct\u003e\u003cpre id=p_10_8\u003e  24%\u003c/pre\u003e\u003ctd class=txt\u003eएक तस्वीर जिसमें दो लोगों को कैफीन की ज़रूरत है\u003ctr\u003e\u003ctd id=td_0_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_9\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_9 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_9\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003eo imagine a doi tipi care au nevoie de apă\u003ctr\u003e\u003ctd id=td_0_10 style=background-color:#f6fcf4 class=pct\u003e\u003cpre id=p_0_10\u003e   1%\u003c/pre\u003e\u003ctd id=td_1_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_10\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_10 style=background-color:#f6fcf4 class=pct\u003e\u003cpre id=p_2_10\u003e   2%\u003c/pre\u003e\u003ctd id=td_3_10 style=background-color:#f6fcf4 class=pct\u003e\u003cpre id=p_3_10\u003e   1%\u003c/pre\u003e\u003ctd id=td_4_10 style=background-color:#f6fcf4 class=pct\u003e\u003cpre id=p_4_10\u003e   1%\u003c/pre\u003e\u003ctd id=td_5_10 style=background-color:#78c679 class=pct\u003e\u003cpre id=p_5_10\u003e  98%\u003c/pre\u003e\u003ctd id=td_6_10 style=background-color:#f2faef class=pct\u003e\u003cpre id=p_6_10\u003e   7%\u003c/pre\u003e\u003ctd id=td_7_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_10\u003e   1%\u003c/pre\u003e\u003ctd id=td_8_10 style=background-color:#f6fcf4 class=pct\u003e\u003cpre id=p_8_10\u003e   2%\u003c/pre\u003e\u003ctd id=td_9_10 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_10\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_10 style=background-color:#f5fbf3 class=pct\u003e\u003cpre id=p_10_10\u003e   3%\u003c/pre\u003e\u003ctd class=txt\u003efoto para penulis SigLIP\u003ctr\u003e\u003ctd id=td_0_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_11\u003e   1%\u003c/pre\u003e\u003ctd id=td_1_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_11\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_11 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_11\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003eロックバンドの写真\u003ctr\u003e\u003ctd id=td_0_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_12 style=background-color:#d3eecd class=pct\u003e\u003cpre id=p_4_12\u003e  40%\u003c/pre\u003e\u003ctd id=td_5_12 style=background-color:#7ac77b class=pct\u003e\u003cpre id=p_5_12\u003e  96%\u003c/pre\u003e\u003ctd id=td_6_12 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_6_12\u003e 100%\u003c/pre\u003e\u003ctd id=td_7_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_12\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_12 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_12\u003e   1%\u003c/pre\u003e\u003ctd class=txt\u003efoto av forskare på Google Brain\u003ctr\u003e\u003ctd id=td_0_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_13\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_13 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_13\u003e   1%\u003c/pre\u003e\u003ctd id=td_2_13 style=background-color:#f1faee class=pct\u003e\u003cpre id=p_2_13\u003e   9%\u003c/pre\u003e\u003ctd id=td_3_13 style=background-color:#f0f9ed class=pct\u003e\u003cpre id=p_3_13\u003e  10%\u003c/pre\u003e\u003ctd id=td_4_13 style=background-color:#d3eecd class=pct\u003e\u003cpre id=p_4_13\u003e  40%\u003c/pre\u003e\u003ctd id=td_5_13 style=background-color:#92d28f class=pct\u003e\u003cpre id=p_5_13\u003e  83%\u003c/pre\u003e\u003ctd id=td_6_13 style=background-color:#afdfa8 class=pct\u003e\u003cpre id=p_6_13\u003e  66%\u003c/pre\u003e\u003ctd id=td_7_13 style=background-color:#dbf1d5 class=pct\u003e\u003cpre id=p_7_13\u003e  34%\u003c/pre\u003e\u003ctd id=td_8_13 style=background-color:#f1faee class=pct\u003e\u003cpre id=p_8_13\u003e   9%\u003c/pre\u003e\u003ctd id=td_9_13 style=background-color:#edf8e9 class=pct\u003e\u003cpre id=p_9_13\u003e  14%\u003c/pre\u003e\u003ctd id=td_10_13 style=background-color:#c2e7bb class=pct\u003e\u003cpre id=p_10_13\u003e  53%\u003c/pre\u003e\u003ctd class=txt\u003eOpenAI:n tutkijoiden kuva\u003ctr\u003e\u003ctd id=td_0_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_14\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_14 style=background-color:#8ace88 class=pct\u003e\u003cpre id=p_8_14\u003e  88%\u003c/pre\u003e\u003ctd id=td_9_14 style=background-color:#a4da9e class=pct\u003e\u003cpre id=p_9_14\u003e  73%\u003c/pre\u003e\u003ctd id=td_10_14 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_14\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003esapi\u003ctr\u003e\u003ctd id=td_0_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_15\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_15 style=background-color:#e9f7e5 class=pct\u003e\u003cpre id=p_8_15\u003e  19%\u003c/pre\u003e\u003ctd id=td_9_15 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_9_15\u003e 100%\u003c/pre\u003e\u003ctd id=td_10_15 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_15\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003eune vache en smoking\u003ctr\u003e\u003ctd id=td_0_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_3_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_4_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_4_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_5_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_6_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_16\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_16 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_8_16\u003e 100%\u003c/pre\u003e\u003ctd id=td_9_16 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_9_16\u003e  99%\u003c/pre\u003e\u003ctd id=td_10_16 style=background-color:transparent class=pct\u003e\u003cpre id=p_10_16\u003e   0%\u003c/pre\u003e\u003ctd class=txt\u003eפרה על החוף\u003ctr\u003e\u003ctd id=td_0_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_0_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_1_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_1_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_2_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_2_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_3_17 style=background-color:#f5fbf3 class=pct\u003e\u003cpre id=p_3_17\u003e   3%\u003c/pre\u003e\u003ctd id=td_4_17 style=background-color:#e7f6e3 class=pct\u003e\u003cpre id=p_4_17\u003e  22%\u003c/pre\u003e\u003ctd id=td_5_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_5_17\u003e   1%\u003c/pre\u003e\u003ctd id=td_6_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_6_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_7_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_7_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_8_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_8_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_9_17 style=background-color:transparent class=pct\u003e\u003cpre id=p_9_17\u003e   0%\u003c/pre\u003e\u003ctd id=td_10_17 style=background-color:#75c477 class=pct\u003e\u003cpre id=p_10_17\u003e 100%\u003c/pre\u003e\u003ctd class=txt\u003eslika prijenosnog računala sa zaključanim zaslonom, šalica cappuccina, mlinci za sol i papar. Pogled kroz prozor otkriva jezero Zürich i Alpe u pozadini grada."
            ],
            "text/plain": [
              "\u003cIPython.core.display.HTML object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/javascript": [
              "\n",
              "  function update(b) {\n",
              "    for(var iimg = 0; iimg \u003c logits.length; iimg++) {\n",
              "      for(var itxt = 0; itxt \u003c logits[iimg].length; itxt++) {\n",
              "        const el = document.getElementById(`p_${iimg}_${itxt}`);\n",
              "        const p = Math.round(100 / (1 + Math.exp(-logits[iimg][itxt] - b)));\n",
              "        const pad = p \u003c 10.0 ? '  ' : p \u003c 100.0 ? ' ' : ''\n",
              "        el.innerHTML = pad + (p).toFixed(0) + '%';\n",
              "\n",
              "        const td = document.getElementById(`td_${iimg}_${itxt}`);\n",
              "        const c = cmap[Math.round(p / 100 * (cmap.length - 1))];\n",
              "        td.style.backgroundColor = c;\n",
              "      }\n",
              "    }\n",
              "  }\n",
              "  "
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/javascript": [
              "\n",
              "  const value = document.querySelector(\"#value\");\n",
              "  const input = document.querySelector(\"#b\");\n",
              "  value.textContent = input.value;\n",
              "  input.addEventListener(\"input\", (event) =\u003e {\n",
              "    value.textContent = event.target.value;\n",
              "    update(event.target.value);\n",
              "  });\n",
              "  "
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/javascript": [
              "update(-10.0)"
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "application/javascript": [
              "google.colab.output.resizeIframeToContent()"
            ],
            "text/plain": [
              "\u003cIPython.core.display.Javascript object\u003e"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "# The same checkpoint also works well across a wide array of langauges.\n",
        "# Note that we adapt the bias a bit to correct for preponderance of English.\n",
        "make_table(zimg, embed_texts(texts_dict.values())[1], images, texts_dict.values(), {**out, 'b': np.array(-10.0)})"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vd9_TZRxjtFK"
      },
      "source": [
        "# Naflex\n",
        "\n",
        "Example to compare the aspect-preserving NaFlex preprocessing with resizing to fixed-resolution square."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "obR29Tzjoy6Q",
        "outputId": "b7a62c0c-de7f-4418-ef33-b5f70e16f5bb"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "(1000, 2853)\n"
          ]
        }
      ],
      "source": [
        "# Example document image with height \u003e\u003e width.\n",
        "img = PIL.Image.open('siglip2_screenshot.jpg')\n",
        "print(img.size)\n",
        "# img  # show image in original resolution"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "4ccyCKIiwImu",
        "outputId": "eb24e2ee-4cea-444a-b850-6d9c13f849c2"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "(1024, 768) (1024,) (1024,) (1024,)\n"
          ]
        }
      ],
      "source": [
        "# Split the image into 1024 naflex patches of size 16.\n",
        "pp_naflex = get_pp_naflex(1024, 16)\n",
        "\n",
        "# These are encoded as the actual patches, input mask, y and x indices.\n",
        "patches, input_mask, yidx, xidx = map(np.array, pp_naflex(dict(image=np.array(img)))['image'])\n",
        "print(patches.shape, input_mask.shape, yidx.shape, xidx.shape)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "LJGkqWEexmaq",
        "outputId": "c1a35f23-7ecc-46e2-9d20-d1c626969091"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "19"
            ]
          },
          "execution_count": 13,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "patches, yidx, xidx = map(lambda x: x[:input_mask.sum()], (patches, yidx, xidx))  # remove padding\n",
        "cols = xidx.max() + 1\n",
        "cols"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 411
        },
        "id": "OwKOYB2xyBdj",
        "outputId": "252ca20c-e03a-45b6-a70d-9d8ea19904f5"
      },
      "outputs": [
        {
          "data": {
            "text/plain": [
              "Text(0.5, 1.0, 'yidx')"
            ]
          },
          "execution_count": 14,
          "metadata": {},
          "output_type": "execute_result"
        },
        {
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAo0AAALzCAYAAAB0hT38AAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAewgAAHsIBbtB1PgAARy1JREFUeJzt3Xt4FPXd///X5rA5Q0RADEGChBCoXpZCEAQbqKefFAmBamtrBQGx1abS+sVzabXVW0AFm7tVkCBiW7VSb7gRaau9MSiKmBYvbQERBEsOKkHklONm5/dHypCYw2cn7DnPx3XtdU12PvPZz7Du29fOzM7HZVmWJQAAAKATMaEeAAAAAMIfoREAAABGhEYAAAAYERoBAABgRGgEAACAEaERAAAARoRGAAAAGBEaAQAAYERoBAAAgBGhEQAAAEaERgAAABgRGgEAAGBEaAQAAIARoREAAABGhEYAAAAYERoBAABgRGgEAACAEaERAAAARoRGAAAAGBEaEVH2798vl8sll8ulrKwsv/U7YcIEu9/XXnvNb/0CQDiilqIrCI0AAAAwIjQCAADAiNAIAAAAo7hQDwBwIisrS5ZlhXoYABDRqKXoCo40AgAAwIjQCAAAACNCIwLqo48+Uo8ePexbMCxcuNC4zY9+9CO7/YABA3T48GF7ndPbRHi9Xj399NO67LLL1K9fPyUmJiorK0sFBQVau3atT/vQ0NCgr33ta/brTpo0ybjNn/70J7t9fHy8tm7d6tNrAUB7LrjgArumPPvssz5vN2PGDHu7n/70p/bz1FJ0iQUE2OrVqy1JliQrPj7eKisr67DtSy+9ZLeNiYmxNm3a1Gr9vn377PUDBw7s9HWrqqqsCy+80G7f3qOwsNA6evSolZ+fbz/35de0LMvauXOnlZycbLf59a9/3eHrHjhwwDrjjDPstvfdd1+n4wQAk+LiYrumXHrppT5tc+TIkVZ161//+pe9jlqKriA0IiiuvfZa+4Ofk5NjHT9+vE2bqqoqq0+fPna7O++8s00bXwvd4cOHrWHDhrUqaoMGDbK++93vWjfccIM1evRo+/np06cbC51lWdayZcvsNomJidb777/fpk1TU5M1YcIEu924ceMsj8fj878TALTn8OHDVlJSkiXJcrlc1r59+4zbPPHEE3YtGjt2bKt11FJ0BaERQfHFF19YAwcOtAvAnDlzWq33er3WFVdcYa8fNWqU1dDQ0KYfXwvdrFmz7HZut9sqKSlp0+btt9+2x+R2u42FzrIsa+rUqXa7888/36qrq2u1/oEHHrDX9+zZ06fCDgC+mDFjhl1fFixYYGyfl5dnt/9yDaSWoisIjQia119/3YqNjbULwYsvvmive/TRR+3nU1JSrA8++KDdPnwpdB988IHlcrnsdqtWrepwTB988EGrUyWmQlddXW1lZGTYbX/84x/b695++20rLi7OXvf73/++838QAHBgy5Ytdn0555xzrKampg7bvvfee3bbtLS0Nmd3qKXoCkIjgmrBggV2IejVq5dVXl5uvfvuu1ZCQoL9/JNPPtnh9r4Uuttvv91uM3r0aOOY7r77bp8LnWVZ1quvvmoXUpfLZb388svWsWPHrOzsbLuP733ve8bXBQCnvvKVr9h15s9//nOH7W699Va73Y033thmPbUUXUFoRFB5PB7roosusgvCxIkTreHDh9t/T5s2rdPtfSl0LU/JFBcXG8f0wQcfOCp0ltW6mJ511lnWt771LfvvrKws68iRI8Y+AMCppUuX2rXm6quvbrdNfX29deaZZ9rt3n777TZtqKXoCkIjgu6jjz6yevTo0aq4SLL69+9vHTp0qNNtTYXO6/W2uqams19qt9SrVy9Hha6hocEaOXJkm32IjY21tmzZ4tNrAoBTn3/+uZWYmGhfP1hdXd2mzfPPP9/qesH2UEvRFdynEUE3aNAg/fa3v231nMvl0urVq9WrV6/T6vvIkSNqaGiw/z7nnHN82s7XdifFx8frD3/4g1JSUlo9f++99+qiiy5y1BcA+OqMM87Qt771LUnN9z185pln2rQpKSmxl+fMmdOl16GWoj2ERoRE3759W/199tln68ILLzztfo8fP97q7+TkZJ+2+3LB8kWPHj2UlJTU6rmpU6c67gcAnJg7d6693DIgStK///1vvfrqq5KkhIQEXXfddV16DWop2kNoRNBVV1drxowZrZ6rrKzUvHnzTrvv1NTUVn/X1NT4tN2JEyccvY5lWZo5c6aqq6tbPX/99dervr7eUV8A4MTFF1+s3NxcSdI///lPbdu2zV731FNPyev1SpKmTZvW5bM31FK0h9CIoJszZ46qqqokSdnZ2YqNjZUkrVixwufpqDrSs2dPud1u++9///vfPm134MABR6+zdOlS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\n",
            "text/plain": [
              "\u003cFigure size 400x400 with 2 Axes\u003e"
            ]
          },
          "metadata": {
            "image/png": {
              "height": 377,
              "width": 326
            }
          },
          "output_type": "display_data"
        }
      ],
      "source": [
        "# Visualizing the indices\n",
        "_, axs = plt.subplots(1, 2, figsize=(4, 4))\n",
        "axs[0].matshow(xidx.reshape([-1, cols]))\n",
        "axs[0].set_title('xidx')\n",
        "axs[1].matshow(yidx.reshape([-1, cols]))\n",
        "axs[1].set_title('yidx')"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 869
        },
        "id": "wPwegN9szoTR",
        "outputId": "4524a662-d6e7-4555-d5e8-8814f2cbd698"
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\u003cimg src=\"\"/\u003e"
            ],
            "text/plain": [
              "\u003cIPython.core.display.HTML object\u003e"
            ]
          },
          "execution_count": 15,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "import einops\n",
        "patches_rearranged = einops.rearrange(patches.reshape([-1, cols, PATCH_SIZE, PATCH_SIZE, 3]), 'r c y x z -\u003e (r y) (c x) z')\n",
        "img_naflex = PIL.Image.fromarray((patches_rearranged * 127.5 + 127.5).astype('uint8'))\n",
        "# (work around broken saved outputs)\n",
        "HTML(img2html(img_naflex))\n",
        "# Note how 1024 patches represent the text somewhat readable thanks to NaFlex..."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 533
        },
        "id": "qFxylZ_QTASu",
        "outputId": "8ad5dea5-22a9-416d-e3ac-8d8a17922bb0"
      },
      "outputs": [
        {
          "data": {
            "text/html": [
              "\u003cimg src=\"\"/\u003e"
            ],
            "text/plain": [
              "\u003cIPython.core.display.HTML object\u003e"
            ]
          },
          "execution_count": 16,
          "metadata": {},
          "output_type": "execute_result"
        }
      ],
      "source": [
        "# ...compared to the resize to square with the same number of patches (and pixels).\n",
        "img_resize_to_square = img.resize([32 * 16, 32 * 16])\n",
        "HTML(img2html(img_resize_to_square))"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "tcf7tnEAPLwo"
      },
      "outputs": [],
      "source": []
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "gpuType": "T4",
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
